#include <iostream>
#include <sys/shm.h>
#include <sys/ipc.h>
#include <sys/types.h>
#include <cassert>
#define PATHNAME "/home/pst/linux/Linux29"
#define ID 2025
#define SIZE 4096
#define MODE 0666
using namespace std;


template <class T>
class Pipe
{
public:
    Pipe(const char* pathname = PATHNAME,int id = ID,size_t size = SIZE)
        :_n(new int())
    {
        key_t key = ftok(pathname,id);
        if(key == -1)
        {
            perror("ftok");
            exit(1);
        }
        _key = key;
        CreSharedSpace(size);

    }

    T* grtshmaddr()
    {
        return _shmaddr;
    }

    ~Pipe()
    {
        if((*_n)--)
        {
            shmdt(_shmaddr);
            if((*_n) == 0)
            {
                delete _n;
            }
            
        }
        
    }
private:
    void CreSharedSpace(size_t size = SIZE)
    {
        int shmid = shmget(_key,size,IPC_CREAT | IPC_EXCL | MODE);
        if(shmid == -1)
        {
            if(*_n == 1)
            {
                
                Getshmat(shmid);
            }
            else
            {
                cout << (*_n) <<" _key:" << _key <<endl;
                perror("shmget");
                exit(2);
            }
            return;         
        }

        Getshmat(shmid);

    }

    void Getshmat(int shmid)
    {
        T* ret = (T*)shmat(shmid,nullptr,0);
        if(ret == (T*)-1)
        {
            cout << (*_n) <<" _key:" << _key << "  shmid:" << shmid <<endl;
            perror("shmat");
            exit(3);
        }
        (*_n)++;
        _shmaddr = ret;
        _shmid = shmid;
        cout << (*_n) <<" _key:" << _key << "  shmid:" << _shmaddr <<endl;
    }

    key_t _key;
    int _shmid;
    int * _n;
    T* _shmaddr;
};